package com.superbytecode.stencil.wrapper;

import com.superbytecode.stencil.consts.StencilConst;
import com.superbytecode.stencil.entities.ConnectionObj;
import com.superbytecode.stencil.entities.DatasourceContext;
import com.superbytecode.stencil.repository.domain.Datasource;
import com.superbytecode.stencil.enums.DatabaseTypeEnum;
import com.superbytecode.stencil.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;

/**
 * All rights Reserved, Designed By www.super-master.com
 *
 * @ProjectName: code-stencil
 * @Package: com.superbytecode.stencil.structure
 * @ClassName: DatasourceFactory
 * @Description: []
 * <p> </p>
 * @Author: [Lance Ting]
 * @Date: 2024/10/12 15:55
 * @Version: V1.0
 * @Copyright: 2024 www.super-master.cn Inc. All rights reserved.
 * TODO: 注意,本文件Lance Ting所作,如果转载或使用请标明具体出处!
 **/
@Slf4j
public class DataSourceSelector {
    final private Datasource configure;

    public static DataSourceSelector builder(Datasource configure) {
        if (Objects.isNull(configure)) {
            throw new IllegalStateException("data source config must be exists!!");
        }
        return new DataSourceSelector(configure);
    }

    public DatasourceContext build() {
        DatasourceContext context = new DatasourceContext();
        context.setPackageName(this.configure.getPackageName());
        String category = this.configure.getCategory();
        String categoryLTS = this.configure.getCategoryLTS();
        // 是否支持该数据库配置
        DatabaseTypeEnum databaseType = DatabaseTypeEnum.of(category, categoryLTS);
        context.setCategory(databaseType.getCategoryCode());
        context.setCategoryLTS(databaseType.getCategoryLTS());
        // 构建数据库认证对象
        String urlPattern = databaseType.getUrlPattern();
        ConnectionObj connectionObj = obtainConnectionObj(urlPattern, this.configure);
        connectionObj.setDriverClass(databaseType.getDriverClass());
        context.setConnection(connectionObj);
        return context;
    }

    /**
     * 获取数据库认证信息对象
     *
     * @param urlPattern jdbcUrl数据格式
     *                   <p>如mysql格式：：jdbc:mysql://{db_host}:{db_port}/{db_name}?xxx</p>
     * @param config     数据源配置
     * @return 数据库认证信息对象
     */
    private ConnectionObj obtainConnectionObj(String urlPattern, Datasource config) {
        ConnectionObj connectionObj = new ConnectionObj();
        if (StencilConst.DB_REGION_REQUIRES.stream().noneMatch(urlPattern::contains)) {
            throw new IllegalArgumentException("database url pattern is not valid");
        }
        String jdbcHost = config.getJdbcHost();
        Integer jdbcPort = config.getJdbcPort();
        String jdbcName = config.getJdbcName();
        String jdbcUrl = urlPattern.replace(StencilConst.DB_REGION_HOST, jdbcHost)//
                .replace(StencilConst.DB_REGION_PORT, String.valueOf(jdbcPort))//
                .replace(StencilConst.DB_REGION_NAME, jdbcName);
        connectionObj.setJdbcUrl(jdbcUrl);
        String username = config.getUsername();
        if (StringUtil.isBlank(username)) {
            throw new IllegalArgumentException("database username must be not null!");
        }
        connectionObj.setDatabaseName(jdbcName);
        connectionObj.setUsername(username);
        connectionObj.setPassword(config.getPassword());
        return connectionObj;
    }

    private DataSourceSelector(Datasource configure) {
        this.configure = configure;
    }
}